﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Collections.ObjectModel;
using HigLabo.WindowsAzure.RestService.Extensions;

namespace HigLabo.WindowsAzure.RestService.ServiceManagement
{
    public class SubscriptionOperationCollection
    {
        public static readonly String ElementName = "SubscriptionOperationCollection";

        public String ContinuationToken { get; private set; }

        private Collection<SubscriptionOperation> _SubscriptionOperations = new Collection<SubscriptionOperation>();
        public IEnumerable<SubscriptionOperation> SubscriptionOperations
        {
            get { foreach (var item in _SubscriptionOperations) { yield return item; } }
        }

        public SubscriptionOperationCollection(XElement xml)
        {
            IEnumerable<XElement> els; XElement el;
            if (xml == null)
            {
                throw new ArgumentNullException("xml");
            }
            /*SubscriptionOperations*/
            el = xml.ElementByLocalName("SubscriptionOperations");
            if (el != null)
            {
                els = el.ElementsByLocalName(SubscriptionOperation.ElementName);
                foreach (var item in els)
                {
                    var add = new SubscriptionOperation(item);
                    this._SubscriptionOperations.Add(add);
                }
            }
            ContinuationToken = xml.ValueOrEmpty("ContinuationToken");
        }
    }

    public class SubscriptionOperation
    {
        public static readonly String ElementName = "SubscriptionOperation";

        public String OperationId { get; private set; }
        public String OperationObjectId { get; private set; }
        public OperationName? OperationName { get; private set; }

        public String OperationStartedTime { get; private set; }
        public String OperationCompletedTime { get; private set; }

        public OperationCaller OperationCaller { get; private set; }
        public SubscriptionOperationStatus OperationStatus { get; private set; }

        private Collection<OperationParameter> _OperationParameters = new Collection<OperationParameter>();
        public IEnumerable<OperationParameter> OperationParameters 
        {
            get { foreach (var item in _OperationParameters) { yield return item; } }
        }

        public SubscriptionOperation(XElement xml)
        {
            IEnumerable<XElement> els;
            XElement el;
            if (xml == null)
            {
                throw new ArgumentNullException("xml");
            }
            /*SubscriptionOperation*/
            this.OperationId = xml.ValueOrEmpty("OperationId");
            this.OperationObjectId = xml.ValueOrEmpty("OperationObjectId");
            this.OperationName = xml.ValueToEnum<ServiceManagement.OperationName>("OperationName");

            el = xml.ElementByLocalName("OperationParameters");
            if (el != null)
            {
                els = el.ElementsByLocalName(OperationParameter.ElementName);
                foreach (var item in els)
                {
                    var add = new OperationParameter(item);
                    this._OperationParameters.Add(add);
                }
            }

            el = xml.ElementByLocalName("OperationCaller");
            if ( el != null)
            {
                OperationCaller = new OperationCaller(el);
            }
            el = xml.ElementByLocalName("OperationStatus");
            if (el != null)
            {
                OperationStatus = new SubscriptionOperationStatus(el);
            }
            this.OperationStartedTime = xml.ValueOrEmpty("OperationStartedTime");
            this.OperationCompletedTime = xml.ValueOrEmpty("OperationCompletedTime");
        }
    }

    public class SubscriptionOperationStatus
    {
        public class OperationStatusError
        {
            public static readonly String ElementName = "Error";
            public String Code { get; private set; }
            public String Message { get; private set; }
            public OperationStatusError(XElement xml)
            {
                if (xml == null)
                    throw new ArgumentNullException("xml");
                Code = xml.ValueOrEmpty("Code");
                Message = xml.ValueOrEmpty("Message");
            }
        }

        public String ID { get; private set; }
        public OperationStatus? Status { get; private set; }
        public String HttpStatusCode { get; private set; }
        public OperationStatusError Error { get; private set; }

        public SubscriptionOperationStatus(XElement xml)
        {
            XElement el;
            if (xml == null)
                throw new ArgumentNullException("xml");
            ID = xml.ValueOrEmpty("ID");
            Status = xml.ValueToEnum<OperationStatus>("Status");
            HttpStatusCode = xml.ValueOrEmpty("HttpStatusCode");
            el = xml.ElementByLocalName(OperationStatusError.ElementName);
            if (el != null)
            {
                Error = new OperationStatusError(el);
            }
        }
    }

    public class OperationParameter
    {
        public static readonly String ElementName = "OperationParameter";
        public String Name { get; private set; }
        public String Value { get; private set; }
        public OperationParameter(XElement xml)
        {
            if (xml == null)
            {
                throw new ArgumentNullException("xml");
            }
            this.Name = xml.ValueOrEmpty("Name");
            this.Value = xml.ValueOrEmpty("Value");
        }
    }

    public class OperationCaller
    {
        public Boolean? UsedServiceManagementApi { get; private set; }
        public String UserEmailAddress { get; private set; }
        public String SubscriptionCertificateThumbprint { get; private set; }
        public String ClientIP { get; private set; }

        public OperationCaller(XElement xml)
        {
            if(xml == null)
            {
                throw new ArgumentNullException("xml");
            }
            UsedServiceManagementApi = xml.ValueToBoolean("UsedServiceManagementApi");
            UserEmailAddress = xml.ValueOrEmpty("UserEmailAddress");
            SubscriptionCertificateThumbprint = xml.ValueOrEmpty("SubscriptionCertificateThumbprint");
            ClientIP = xml.ValueOrEmpty("ClientIP");
        }
    }
}
